package br.com.unifebe.tcc.componente.GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collection;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

@SuppressWarnings("serial")
public abstract class LookupEdit<E extends Object>  extends JPanel {

	private JMLEdit edit;
	private JButton button;
	private JLabel infLabel;
	protected E userObject;
	
	private Collection<ActionListener> actionListeners;
	
	public abstract void acaoDoBotao();
	public abstract void acaoDoEnter();
	
	public LookupEdit() {
		super();
		initComponentes();
		validate();
	}
	
	public void initComponentes() {
		this.setPreferredSize(new Dimension(75,21));
		this.setLayout(new BorderLayout());
		this.add( getButton(),BorderLayout.EAST);
		this.add( getEdit(),BorderLayout.CENTER);
	}	
	
	
	
	public JButton getButton() {
		if (button==null) {
			button = new JButton() {
				  @Override
				protected void paintComponent(Graphics g) {
					    if (getModel().isArmed()) {
					      g.setColor(Color.lightGray);
					    } else {
					      g.setColor(getBackground());
					    }
					    g.fillRoundRect(0, 0, getSize().width-1, 
					      getSize().height-1,1,1);

					    super.paintComponent(g);
					  }
			};
			button.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.LIGHT_GRAY));
			button.setPreferredSize(new Dimension(21,18));
			button.setFocusable(false);
			button.setIconTextGap(0);
			button.setText("...");
			button.setHorizontalAlignment(SwingConstants.CENTER);
			button.setContentAreaFilled(false);
			button.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent e) {
//					fireActionListeners( e );
					acaoDoBotao();
				}
			});
		}
		return button;
	}
	
	
	public JMLEdit getEdit() {
		if (edit==null) {
			edit = new JMLEdit();
			edit.setSize(80,21);
			edit.addKeyListener(new KeyAdapter(){
				@Override
				public void keyPressed(KeyEvent e) {
					int event = Parametros.getTeclaAtalhoPesquisa();
					if(e.getKeyCode()==event || e.getKeyCode()==KeyEvent.VK_F9) {
						getButton().doClick();
					}
					if(e.getKeyCode()==event || e.getKeyCode()==KeyEvent.VK_ENTER ) {
						acaoDoEnter();
					}
				}
			});
			edit.addFocusListener(new FocusAdapter(){
				@Override
				public void focusGained(FocusEvent e) {
					if (!e.isTemporary()) {
						((JMLEdit)e.getSource()).selectAll();
					}
				}
			});
			
			edit.addFocusListener(new FocusListener(){
				@Override
				public void focusLost(FocusEvent e) {
					fireFocusLostListener( e ); 
				}
				@Override
				public void focusGained(FocusEvent e) {
					fireFocusGainedListener( e ); 
				}
			});
			
			edit.addKeyListener(new KeyListener() {
				@Override
				public void keyPressed(KeyEvent e) {
					fireKeyPressedListener( e );
				}
				@Override
				public void keyReleased(KeyEvent e) {
					fireKeyReleasedListener( e );
				}
				@Override
				public void keyTyped(KeyEvent e) {
					fireKeyTypedListener( e );
				}
			});
		}
		return edit;
	}
	
	public void addActionListener(ActionListener l) {
		if (l!=null) {
			if (getActionListeners().contains( l )) {
				getActionListeners().remove( l );
			}
			getActionListeners().add( l );
		}
	}
	
	private void fireFocusLostListener(FocusEvent e) {
		for(FocusListener f : getFocusListeners() ) {
			f.focusLost( e );
		}
	}

	private void fireFocusGainedListener(FocusEvent e) {
		for(FocusListener f : getFocusListeners()) {
			f.focusGained( e );
		}
	}
	
	public void fireKeyPressedListener(KeyEvent e) {
		for(KeyListener k : getKeyListeners()) {
			k.keyPressed( e );
		}
	}

	private void fireKeyReleasedListener(KeyEvent e) {
		for(KeyListener k : getKeyListeners()) {
			k.keyReleased( e );
		}
	}
	
	private void fireKeyTypedListener(KeyEvent e) {
		for(KeyListener k : getKeyListeners()) {
			k.keyTyped( e );
		}
	}

	private void fireActionListeners(ActionEvent e) {
		for(ActionListener a : getActionListeners()) {
			a.actionPerformed( e );
		}
	}

	@Override
	public void setEnabled(boolean b) {
		super.setEnabled( b );
		this.getEdit().setEnabled( b );
		this.getEdit().setEditable( b );
		this.getEdit().setFocusable( b );
		this.getButton().setEnabled( b );
	}
	
	public Collection<ActionListener> getActionListeners() {
		if (actionListeners == null) {
			actionListeners = new ArrayList<ActionListener>();
		}
		return actionListeners;
	}
	
	@Override
	public void requestFocus() {
		super.requestFocus();
		if (getEdit() != null) {
			getEdit().requestFocus();
		}
	}
	
	@Override
	public void grabFocus() {
		super.grabFocus();
		if (getEdit() != null) {
			getEdit().grabFocus();
		}
	}
	
	@Override
	public void setFocusable(boolean focusable) {
		super.setFocusable(focusable);
		
		if (getEdit() != null) {
			getEdit().setFocusable(focusable);
		}
	}
	
	@Override
	public boolean isFocusOwner() {
		return getEdit().isFocusOwner();
	}
	
	public void setEditable(boolean b) {
	   getEdit().setEditable( b );
	}
	
	public JLabel getInfLabel() {
		if (infLabel==null) {
			infLabel = new JLabel();
			infLabel.setPreferredSize(new Dimension( 250, 20 ) );
		}
		return infLabel;
	}

	public void setInfLabel(JLabel infLabel) {
		this.infLabel = infLabel;
	}
	
	public Integer getInteger() {
		return Integer.parseInt(getEdit().getText());
	}

	public Long getLong() {
		return Long.parseLong(getEdit().getText());
	}
	
	public E getUserObject() {
		return userObject;
	}
	
	public void setUserObject( E userObject ){
		this.userObject = userObject;
	}
}
